

#include "Timer.h"
#include <cstddef>

namespace zepco {


bool Timer::cancel() {
    std::unique_lock<std::shared_mutex> write_lock(m_manger->m_mtx);
    if (m_callback == nullptr) {
        return false;
    } else {
        m_callback = nullptr;
    }
    auto it = m_manger->m_timers.find(shared_from_this()); // 在堆中查找定时器
    if (it != m_manger->m_timers.end()) {
        m_manger->m_timers.erase(it);
    }
    return true;
}


// 刷新定时器的时间 会将当前定时器的触发事件延后
bool Timer::refresh() {
    std::unique_lock<std::shared_mutex> write_lock(m_manger->m_mtx);
    if (m_callback == nullptr) {
        return false;
    }

    auto it = m_manger->m_timers.find(shared_from_this());
    if (it == m_manger->m_timers.end()) {
        return false;
    }

    m_manger->m_timers.erase(it);
    m_next = std::chrono::system_clock::now() + std::chrono::milliseconds(m_ms);
    m_manger->m_timers.insert(shared_from_this());
    return true;
}

bool Timer::reset(uint64_t ms, bool from_now) {
    if (ms == m_ms && !from_now) {
        return true;
    }

    {
        std::unique_lock<std::shared_mutex> write_lock(m_manger->m_mtx);
        if (m_callback == nullptr) { // 已经被取消 或未初始化
            return false;
        }

        auto it = m_manger->m_timers.find(shared_from_this());
        if (it == m_manger->m_timers.end()) {
            return false;
        }
        m_manger->m_timers.erase(it);
    }

    //reinsert
    auto start = from_now ? std::chrono::system_clock::now() : m_next - std::chrono::milliseconds(m_ms); // ture -> 重新计算超时时间 false->从上一次起点开始
    m_ms = ms;
    m_next = start + std::chrono::milliseconds(m_ms);
    m_manger->addTimer(shared_from_this());
    return true;
}

Timer::Timer(uint64_t ms, std::function<void()> callback, bool recurring, TimerManager *manger)
    : m_recurring(recurring), m_ms(ms), m_callback(callback), m_manger(manger) {
    auto now = std::chrono::system_clock::now();
    m_next = now + std::chrono::milliseconds(ms);
}

bool Timer::Comparator::operator()(const std::shared_ptr<Timer> &lhs, const std::shared_ptr<Timer> &rhs) const {
    assert(lhs != nullptr && rhs != nullptr);
    return lhs->m_next < rhs->m_next;
}

bool operator<(const std::shared_ptr<Timer> &lhs, const std::shared_ptr<Timer> &rhs) {
    return lhs->m_next < rhs->m_next;
}

//////////////////////////////////////////////////////////

TimerManager::TimerManager() {
    m_previouseTime = std::chrono::system_clock::now();
}

std::shared_ptr<Timer> TimerManager::addTimer(uint64_t ms, std::function<void()> callback, bool recurring) {
    std::shared_ptr<Timer> timer(new Timer(ms, callback, recurring, this));
    addTimer(timer);
    return timer;
}

// lock + tickle()
void TimerManager::addTimer(std::shared_ptr<Timer> timer) {
    bool at_front = false; // 标识插入的时最早的定时器
    {
        std::unique_lock<std::shared_mutex> write_lock(m_mtx);
        auto it = m_timers.insert(timer).first;
        at_front = (it == m_timers.begin()) && !m_tickled;
        if (at_front) {
            m_tickled = true;
        }
    }

    if (at_front) {
        // wake up
        onTimerInsertAtFront(); //具体在ioscheduler
    }
}

// 如果条件存在 -> 执行cb()
static void OnTimer(std::weak_ptr<void> weak_cond, std::function<void()> callback) {
    auto tmp = weak_cond.lock();
    if (tmp) {
        callback();
    }
}

std::shared_ptr<Timer> TimerManager::addConditionTimer(uint64_t ms, std::function<void()> callback, std::weak_ptr<void> weak_cond, bool recurring) {
    return addTimer(ms, std::bind(OnTimer, weak_cond, callback), recurring);
}

uint64_t TimerManager::getNextTimer() {
    std::shared_lock<std::shared_mutex> read_lock(m_mtx);
    m_tickled = false;
    if (m_timers.empty()) {
        return ~0ull;
    }

    auto now = std::chrono::system_clock::now();
    auto time = (*m_timers.begin())->m_next;

    if (now >= time) {
        return 0;
    } else {
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(time - now);
        return static_cast<uint64_t>(duration.count());
    }
}


void TimerManager::listExpiredCb(std::vector<std::function<void()>> &cbs) {
    auto now = std::chrono::system_clock::now();

    std::unique_lock<std::shared_mutex> write_lock(m_mtx);

    bool rollover = deleteClockRollover();
    // 回退 -> 清理所有timer || 超时 -> 清理超时timer
    while (!m_timers.empty() && (rollover || (*m_timers.begin())->m_next <= now)) {
        auto temp = *m_timers.begin();
        m_timers.erase(m_timers.begin());
        cbs.push_back(temp->m_callback);

        if (temp->m_recurring) { //  如果是循环的 当前时间加上他的超时时间重新插入堆中
            temp->m_next = now + std::chrono::milliseconds(temp->m_ms);
            m_timers.insert(temp);
        } else {
            temp->m_callback = nullptr;
        }
    }
}

bool TimerManager::deleteClockRollover() {
    bool rollover = false;
    // 当前时间 now 与上次记录时间 m_previouseTime 减去一个小时间量 (60 * 60 * 1000 毫秒)
    auto now = std::chrono::system_clock::now();
    // 当前时间 now 小于这个时间值 -> 系统时间回滚
    if(now < (m_previouseTime - std::chrono::milliseconds(60 * 60 * 1000))) {
        rollover = true;
    }
    m_previouseTime = now;
    return rollover;
}

}